package com.cctc.mychat.server;

import com.cctc.mychat.common.handler.ReaderIdleStateHandler;
import com.cctc.mychat.common.protocol.codec.MessageCodec;
import com.cctc.mychat.common.protocol.codec.UnpacketDecoder;
import com.cctc.mychat.server.handler.AuthHandler;
import com.cctc.mychat.server.handler.Message.ChatRequestMessageHandler;
import com.cctc.mychat.server.handler.Message.HeartBeatRequestMessageHandler;
import com.cctc.mychat.server.handler.Message.LoginRequestMessageHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.util.Date;

public class MyChatServer {
    private static final int PORT = 8000;

    public static void main(String[] args) {
        final ServerBootstrap bootstrap = new ServerBootstrap();
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());
        bootstrap
                .group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel channel) throws Exception {
                        ChannelPipeline pipeline = channel.pipeline();
                        pipeline.addLast(new ReaderIdleStateHandler(1800))
                                .addLast(new UnpacketDecoder())
                                .addLast(new MessageCodec())
                                .addLast(new LoginRequestMessageHandler())
                                .addLast(new HeartBeatRequestMessageHandler())
                                // .addLast(new AuthHandler())
                                .addLast(new ChatRequestMessageHandler());
                    }
                })
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .childOption(ChannelOption.SO_SNDBUF, 32 * 1024)
                .childOption(ChannelOption.SO_RCVBUF, 32 * 1024)
                .childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1800 * 1000);
        bind(bootstrap, PORT);
    }

    private static void bind(final ServerBootstrap bootstrap, final int port) {
        bootstrap.bind(port).addListener(future -> {
            if (future.isSuccess()) {
                System.out.println("[MyChatServer] Server start success at port (" + port + ").");
            } else {
                System.err.println("[MyChatServer] Failed to start server at port (" + port + ").");
                bind(bootstrap, PORT + 1);
            }
        });
    }

}
